<template>
  <div ref="sceneRef" id="scene" style="width: 100%; height: 100%;"></div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';

const sceneRef = ref(null);

onMounted(() => {
  if (sceneRef.value) {
    const base3d = new Base3d(sceneRef.value);
  } else {
    console.error('Container is not ready');
  }
});

class Base3d {
  constructor(container) {
    this.container = container;
    this.camera;
    this.scene;
    this.renderer;
    this.controls;
    this.model;
    this.init();
    this.animate();
    this.onWindowResize(); // 初始化时调整尺寸
    window.addEventListener('resize', this.onWindowResize.bind(this)); // 监听窗口大小变化
  }

  init() {
    this.initScene();
    this.initCamera();
    this.initRender();
    this.initControls();
    this.addLights();
    this.addMesh();
  }

  initScene() {
    this.scene = new THREE.Scene();
  }

  initCamera() {
    this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    this.camera.position.set(0, 0, 5);
  }

  initRender() {
    this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setSize(window.innerWidth, window.innerHeight);
    this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
    this.renderer.toneMappingExposure = 1;
    this.renderer.setClearColor(0x000000, 0);
    if (this.container) {
      this.container.appendChild(this.renderer.domElement);
    } else {
      console.error('Container is not defined');
    }
  }

  render() {
    this.renderer.render(this.scene, this.camera);
  }

  animate() {
    this.renderer.setAnimationLoop(this.render.bind(this));
  }

  initControls() {
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    this.controls.enableDamping = true;
    this.controls.dampingFactor = 0.05;
    this.controls.enableZoom = false; // 禁用鼠标滚轮缩放
    this.controls.maxPolarAngle = Math.PI / 2; // 限制只能左右旋转
    this.controls.minPolarAngle = Math.PI / 2;
  }

  addLights() {
    // 增加环境光强度
    const ambientLight = new THREE.AmbientLight(0xffffff, 2);
    this.scene.add(ambientLight);

    // 增加方向光强度
    const directionalLight = new THREE.DirectionalLight(0xffffff, 2);
    directionalLight.position.set(10, 10, 10);
    directionalLight.castShadow = true;
    this.scene.add(directionalLight);

    const directionalLight2 = new THREE.DirectionalLight(0xffffff, 2);
    directionalLight2.position.set(-10, 10, -10);
    directionalLight2.castShadow = true;
    this.scene.add(directionalLight2);
  }

  setModel(modelName) {
    return new Promise((resolve, reject) => {
      const dracoLoader = new DRACOLoader();
      dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/'); // 确保链接正确
      dracoLoader.setDecoderConfig({ type: 'js' });
      dracoLoader.preload();

      const loader = new GLTFLoader().setPath('/gltf/'); // 设置模型路径
      loader.setDRACOLoader(dracoLoader); // 将 DRACOLoader 实例设置到 GLTFLoader

      loader.load(modelName, (gltf) => {
        this.model = gltf.scene;
        this.model.scale.set(1, 1, 1);

        // 计算模型的中心点
        function getWorldBoundingBox(object) {
            const box = new THREE.Box3();
            const matrix = new THREE.Matrix4();
            const stack = [];
            stack.push(object);
            while (stack.length > 0) {
                const current = stack.pop();
                matrix.copy(current.matrixWorld);
                const children = current.children;
                if (children.length > 0) {
                    children.forEach(child => {
                        stack.push(child);
                    });
                }
                const geometry = current.geometry;
                if (geometry) {
                    const localBox = new THREE.Box3().setFromBufferAttribute(geometry.attributes.position);
                    localBox.applyMatrix4(matrix);
                    box.union(localBox);
                }
            }
            return box;
        }
        const box = getWorldBoundingBox(this.model);
        const center = new THREE.Vector3();
        box.getCenter(center);
        this.model.position.x -= center.x;
        this.model.position.y -= center.y;
        this.model.position.z -= center.z;

        this.model.position.set(0, -1.1, 0);

        // 初始化时向右旋转 80 度
        this.model.rotation.y = -THREE.MathUtils.degToRad(270); // 顺时针旋转 80 度

        // 手动调整模型的中心点
        this.model.position.y += 1; // 根据需要调整Y轴位置
        // this.model.position.x += 10; // 根据需要调整Y轴位置

        function traverseMaterials(object) {
            if (object.material) {
                const materials = object.material;
                if (Array.isArray(materials)) {
                    materials.forEach(material => {
                        if (material.isMeshStandardMaterial) {
                            material.metallic = 0.5;
                            material.roughness = 0.5;
                        }
                    });
                } else if (materials.isMeshStandardMaterial) {
                    materials.metallic = 0.5;
                    materials.roughness = 0.5;
                }
            }
            const children = object.children;
            if (children && children.length > 0) {
                children.forEach(child => {
                    traverseMaterials(child);
                });
            }
        }
        // 加载模型成功后调用
        traverseMaterials(this.model);

        this.scene.add(this.model);
        resolve(`${modelName} 模型添加成功`);
      }, undefined, (error) => {
        console.error('模型加载失败：', error);
        reject(error);
      });
    });
  }

  addMesh() {
    this.setModel('ai助手.glb') // 确保路径正确
      .then((message) => {
        console.log(message);
      })
      .catch((error) => {
        console.error('模型加载失败：', error);
      });
  }

  onWindowResize() {
    const width = this.container.clientWidth;
    const height = this.container.clientHeight;
    this.camera.aspect = width / height;
    this.camera.updateProjectionMatrix();
    this.renderer.setSize(width, height);
  }
}

onUnmounted(() => {
  window.removeEventListener('resize', this.onWindowResize.bind(this)); // 移除监听
});
</script>